home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 22 / PC Actual CD 22.iso / SHARE / wnt / lemmy30.exe / CPPSCAN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-24  |  21.9 KB  |  922 lines

  1.  
  2. //////////////////////////////////////////////////////////////////////////
  3. //
  4. //  cppscan.c
  5. //
  6. //  Copyright 1997 by James Iuliano
  7. //
  8. //  Permission granted to use this program for development
  9. //  of Lemmy VI editor syntax highlight plug-ins.  Permission
  10. //  for any other use must be obtained by James Iuliano.
  11. //
  12. //////////////////////////////////////////////////////////////////////////
  13.  
  14. #include <windows.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <ctype.h>
  18.  
  19. #include "syntax.h"
  20. #include "cppscan.h"
  21. #include "dlgmacro.h"
  22.  
  23.  
  24. #define C_KEYWORD   0x01
  25. #define CPP_KEYWORD 0x02
  26.  
  27. typedef struct cpp_extra_struct
  28. {
  29.    short keywords;
  30.    BOOL  cpp_comments;
  31. }
  32. cpp_extra_struct;
  33.  
  34. static parse_context_type  *lpPC;
  35. static cpp_extra_struct    *cpp;
  36.  
  37. //
  38. //  Private routines (forward referenced)...
  39. //
  40. //     The scan_... routines will typically set the lpPC->ParseState member
  41. //     based on what they find...
  42. //
  43. static int isodigit(char digit);
  44. static BOOL test_continuation(char *next_token);
  45. static BOOL scan_comment_conditions(char *text);
  46. static char *scan_from_preprocessor(char *next_token, parse_context_type  *lpPC);
  47. static char *scan_comment(char *next_token, parse_context_type *lpPC);
  48. static char *scan_string(char *next_token, parse_context_type *lpPC);
  49. static int is_c_keyword(char *token);
  50.  
  51.  
  52.  
  53. ////////////////////////////////////////////////////////////////////////
  54. //
  55. //  API Definitions...
  56. //
  57. ////////////////////////////////////////////////////////////////////////
  58.  
  59. DllExport(char *) ParseEngineName()
  60. {
  61.    static char name[32];
  62.  
  63.    strcpy( name, "C/C++ Parser" );
  64.    return(name);
  65. }
  66.  
  67.  
  68.  
  69. //
  70. // ..stubs..
  71. //
  72. DllExport(short) ParsePropertiesAvailable()
  73.    return(TRUE); 
  74. }
  75.  
  76.  
  77.  
  78. long FAR PASCAL PropertiesDialogProc(HWND hWnd, WORD iMessage, WORD wParam, DWORD lParam)
  79. {
  80.     switch (iMessage)
  81.     {
  82.         case WM_INITDIALOG:
  83.          SETCK(IDC_DO_CPP,          (cpp->keywords & CPP_KEYWORD));
  84.          SETCK(IDC_DO_CPP_COMMENTS,  cpp->cpp_comments);
  85.          return TRUE;
  86.         break;
  87.         case WM_COMMAND:
  88.               switch (LOWORD(wParam))
  89.             {
  90.             case IDOK:
  91.                if ( GETCK(IDC_DO_CPP) )
  92.                   cpp->keywords = C_KEYWORD | CPP_KEYWORD;
  93.                else
  94.                   cpp->keywords = C_KEYWORD;
  95.  
  96.                cpp->cpp_comments = GETCK(IDC_DO_CPP_COMMENTS);
  97.  
  98.                SaveEngineInfoInt("CPPDoCPPKeywords", (cpp->keywords & CPP_KEYWORD));
  99.                SaveEngineInfoInt("CPPDoCPPComments", cpp->cpp_comments);
  100.  
  101.                EndDialog(hWnd, 0);
  102.                return(TRUE);
  103.             break;
  104.             case IDCANCEL:
  105.                  EndDialog(hWnd, 0);
  106.                  return(TRUE);
  107.             break;
  108.          }
  109.         break;
  110.     }
  111.     return(0L);
  112. }
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119. static void show_system_error()
  120. {
  121.    LPTSTR         lpMsg;
  122.    DWORD          last_error;
  123.  
  124.    last_error = GetLastError();
  125.    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  126.          NULL, last_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
  127.          (LPTSTR) &lpMsg, 0, NULL);
  128.    MessageBox(GetActiveWindow(), lpMsg, "LoadResource", MB_ICONEXCLAMATION);
  129.    LocalFree(lpMsg);
  130. }
  131.  
  132.  
  133.  
  134.  
  135.  
  136. DllExport(short) ParseProperties( parse_context_type *lpPCLocal )
  137. {
  138.     DLGPROC        lpfnDialogProc;
  139.     int            dlg_return;
  140.     static HANDLE  hDialog;
  141.    HINSTANCE      hInst;
  142.    HINSTANCE      hLib;
  143.    HGLOBAL        prop_hGlbl;
  144.    HWND           hWnd;
  145.    HRSRC          dialog_resource;
  146.  
  147.    lpPC  = lpPCLocal;
  148.    cpp   = (cpp_extra_struct *)lpPC->lpExtra;
  149.    hWnd  = GetActiveWindow();
  150.    hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE);
  151.    hLib  = lpPC->hLibrary;
  152.  
  153.     lpfnDialogProc = (DLGPROC)MakeProcInstance((FARPROC)PropertiesDialogProc, hInst);
  154.     if ( lpfnDialogProc == NULL )
  155.     {
  156.       cpp  = NULL;
  157.       lpPC = NULL;
  158.     
  159.       return(FALSE);
  160.     }
  161.  
  162.    dialog_resource = FindResource(hLib, "PROPERTIES", RT_DIALOG);
  163.    if ( dialog_resource != NULL )
  164.    {
  165.       prop_hGlbl = LoadResource(hLib, dialog_resource);
  166.       if ( prop_hGlbl != NULL )
  167.       {
  168.           dlg_return  = DialogBoxIndirect( hInst, (LPDLGTEMPLATE)prop_hGlbl, 
  169.                                           hWnd, lpfnDialogProc );
  170.       }
  171.       else
  172.       {
  173.          show_system_error();
  174.          dlg_return = -1;
  175.       }
  176.    }
  177.    else
  178.    {
  179.       show_system_error();
  180.       dlg_return = -1;
  181.    }
  182.  
  183.     if ( dlg_return < 0 )
  184.     {
  185.         MessageBox( hWnd, "Failed to open property dialog.", "C/C++ Properties", MB_OK );
  186.     }
  187.  
  188.     FreeProcInstance((FARPROC)lpfnDialogProc);
  189.    cpp  = NULL;
  190.    lpPC = NULL;
  191.  
  192.    return(TRUE);
  193. }
  194.  
  195.  
  196.  
  197. DllExport(short) ParseCustomKeywordsSupported()                    { return(0); }
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204. DllExport(short) ParseLoadCustomTokens( parse_context_type *lpPC )
  205. {
  206.    //LoadTokenInfo( &(lpPC->CustomToken[0]) );
  207.    return(0);
  208. }
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215. DllExport(short) ParseSaveCustomTokens( parse_context_type *lpPC ) 
  216.    //SaveTokenInfo( &(lpPC->CustomToken[0]) );
  217.    return(0); 
  218. }
  219.  
  220.  
  221.  
  222.  
  223. DllExport(short) ParseConstructor( parse_context_type *lpPC )
  224. {
  225.    lpPC->lpExtra = (void *)malloc(sizeof(cpp_extra_struct));
  226.    cpp = (cpp_extra_struct *)lpPC->lpExtra;
  227.  
  228.    cpp->cpp_comments = (BOOL)LoadEngineInfoInt("CPPDoCPPComments", TRUE);
  229.  
  230.    cpp->keywords     = C_KEYWORD;
  231.    if ( (BOOL)LoadEngineInfoInt("CPPDoCPPKeywords", TRUE) )
  232.       cpp->keywords |= CPP_KEYWORD;
  233.    
  234.    lpPC->CustomTokenMax         = 0;
  235.  
  236.    cpp = NULL;
  237.  
  238.    return(0);
  239. }
  240.  
  241.  
  242.  
  243.  
  244. DllExport(short) ParseDestructor( parse_context_type *lpPC )
  245. {
  246.    free( lpPC->lpExtra );
  247.    lpPC->lpExtra = NULL;
  248.  
  249.    return(0);
  250. }
  251.  
  252.  
  253.  
  254. DllExport(short) ParseInitRedraw( parse_context_type *lpPC )
  255. {
  256.    return(0);
  257. }
  258.  
  259.  
  260.  
  261. DllExport(short) ParseInitParser( parse_context_type *lpPC )
  262. {
  263.    return(0);
  264. }
  265.  
  266.  
  267.  
  268.  
  269. DllExport(short) ParseBackscan( parse_context_type *lpPC )
  270. {
  271.    char *text;
  272.  
  273.    text = lpPC->lpParseText;
  274.  
  275.    if ( (strlen( text ) >= 2) &&
  276.         ( text[strlen(text)-1] == '\\') )
  277.    {
  278.       return(0);
  279.    }
  280.  
  281.    if ( !scan_comment_conditions(text) )
  282.    {
  283.       return(0);
  284.    }
  285.  
  286.    lpPC->FinishBackscan = TRUE;
  287.    return(0);
  288. }
  289.  
  290.  
  291.  
  292.  
  293.  
  294. DllExport(short) ParseToken( parse_context_type *lpPC )
  295. {
  296.    char  *next_token;
  297.    char  *tmp_pointer;
  298.    char      akeyword[15];        // 
  299.    int    flag_period = FALSE;     // Flag for decimal point on decimal numbers
  300.    int    flag_exp    = FALSE;    // Flag for exponent (E|e) on decimal numbers
  301.  
  302.    cpp = (cpp_extra_struct *)lpPC->lpExtra;
  303.  
  304.    next_token = SkipWhiteSpace( lpPC->lpParseText );
  305.  
  306.    if ( (lpPC->ParseState != st_fresh_start) &&
  307.         (lpPC->PreviousLine < lpPC->ScanningLine) )
  308.    {
  309.       switch ( lpPC->ScannedToken )
  310.       {
  311.          case tk_string:
  312.             next_token = scan_string(next_token, lpPC);
  313.  
  314.             lpPC->lpParseText = SkipWhiteSpace( next_token );
  315.  
  316.             return(0);
  317.          break;
  318.          case tk_comment:
  319.             next_token = scan_comment(next_token, lpPC);
  320.  
  321.             lpPC->lpParseText = SkipWhiteSpace( next_token );
  322.             
  323.             return(0);
  324.          break;
  325.          case tk_preprocessor:
  326.             next_token = scan_from_preprocessor(next_token, lpPC);
  327.       
  328.             lpPC->lpParseText  = next_token;
  329.             lpPC->ScannedToken = tk_preprocessor;
  330.  
  331.             return(0);
  332.          break;
  333.       }
  334.    }
  335.  
  336.    //
  337.    //  Check for preprocessor first...
  338.    //
  339.    if ( (lpPC->ScanColumn == 0) && (*next_token == '#') ) 
  340.    {
  341.        next_token = scan_from_preprocessor(next_token, lpPC);
  342.  
  343.        lpPC->lpParseText  = next_token;
  344.        lpPC->ScannedToken = tk_preprocessor;
  345.        
  346.        return(0);
  347.    }
  348.  
  349.    //
  350.    //  '.' could be either struct or float - advance over the period if float
  351.    //
  352.    if ( *next_token == '.' && isdigit( *(next_token + 1) ) ) 
  353.    {
  354.       flag_period = TRUE;
  355.       next_token++;
  356.    }
  357.  
  358.    //
  359.    //  '_' is really considered alpha
  360.    //  If punctuation of some type...figure it out
  361.    //
  362.    if ( ispunct( *next_token ) && *next_token != '_'  ) 
  363.    {
  364.         // If next token is of STRING type
  365.         if ( *next_token == '"' ) 
  366.         {
  367.             next_token++;
  368.  
  369.             next_token = scan_string(next_token, lpPC);
  370.  
  371.             lpPC->lpParseText    = SkipWhiteSpace( next_token );
  372.             lpPC->ScannedToken = tk_string;
  373.  
  374.              return(0);
  375.         }
  376.  
  377.         // If next token is a single CHAR STRING type
  378.         else if ( *next_token == '\'' ) 
  379.         {
  380.             next_token++;
  381.  
  382.             while ( (*next_token != '\'') && *next_token ) 
  383.             {
  384.                 if ( *next_token == '\\' )
  385.                     next_token++;
  386.  
  387.                 next_token++;
  388.             }
  389.  
  390.             //(*aline) = remove_white_space( ++next_token );
  391.             if ( *next_token ) ++next_token;
  392.  
  393.             lpPC->lpParseText  = SkipWhiteSpace( next_token );
  394.             lpPC->ParseState   = st_fresh_start;
  395.             lpPC->ScannedToken = tk_char;
  396.  
  397.             return(0);
  398.         }
  399.  
  400.         // If next token is of COMMENT (C++ variety) type
  401.         else if ( *next_token == '/' && *(next_token + 1) == '/' && cpp->cpp_comments ) 
  402.         {
  403.             lpPC->lpParseText = &lpPC->lpParseText[strlen(lpPC->lpParseText)]; // null terminator
  404.             lpPC->ParseState = st_fresh_start;
  405.             lpPC->ScannedToken = tk_comment;
  406.  
  407.             return(0);
  408.         }
  409.  
  410.         // If next token is of COMMENT (C variety) type
  411.         else if ( *next_token == '/' && *(next_token + 1) == '*' ) 
  412.         {
  413.             next_token += 2;
  414.             
  415.             next_token = scan_comment(next_token, lpPC);
  416.  
  417.             lpPC->lpParseText = SkipWhiteSpace(next_token);
  418.             lpPC->ScannedToken = tk_comment;
  419.  
  420.             return(0);
  421.         }
  422.  
  423.         //
  424.         //  Default...
  425.         //
  426.         else 
  427.         {
  428.            ++(lpPC->lpParseText);
  429.            lpPC->ParseState   = st_fresh_start;
  430.            lpPC->ScannedToken = tk_none;
  431.            return(0);
  432.         }
  433.     }
  434.  
  435.     // Number of some type ... decimal, hex, or octal
  436.     else if ( isdigit( *next_token ) ) 
  437.     {
  438.         // Hex
  439.         if ( *next_token == '0' && *(next_token + 1) =='x' && !flag_period ) 
  440.         {
  441.             next_token += 2;
  442.  
  443.             if ( !isxdigit( *next_token )) 
  444.          {
  445.                 lpPC->lpParseText    = SkipWhiteSpace(next_token);
  446.                 lpPC->ScannedToken = tk_none;
  447.                 lpPC->ParseState   = st_fresh_start;
  448.                 return(-1);
  449.             }
  450.  
  451.             while ( isxdigit( *next_token ) && *next_token ) 
  452.             {
  453.                 next_token++;
  454.             }
  455.  
  456.             if ( ((tolower( *next_token ) == 'l') || (tolower( *next_token ) == 'u' )) && 
  457.                   !isalnum( *(next_token + 1) ) 
  458.             ) 
  459.             {
  460.                 next_token += 1;
  461.             }
  462.  
  463.             if ( isalpha( *next_token ) ) 
  464.             {
  465.                lpPC->lpParseText    = SkipWhiteSpace(++next_token);
  466.                lpPC->ScannedToken = tk_none;
  467.                lpPC->ParseState   = st_fresh_start;
  468.                return(-1);
  469.             }
  470.  
  471.             lpPC->lpParseText    = SkipWhiteSpace(next_token);
  472.             lpPC->ParseState   = st_fresh_start;
  473.             lpPC->ScannedToken = tk_number;
  474.         }
  475.  
  476.         // Octal..
  477.         else if ( *next_token == '0' && isdigit( *(next_token + 1) ) && !flag_period ) 
  478.         {
  479.             next_token += 1;
  480.  
  481.             while ( isodigit( *next_token ) && *next_token ) 
  482.             {
  483.                 next_token++;
  484.             }
  485.  
  486.             if ( ((tolower( *next_token ) == 'l') || (tolower( *next_token ) == 'u' )) && 
  487.                   !isalnum( *(next_token + 1) ) 
  488.                ) 
  489.             {
  490.                 next_token += 1;
  491.             }
  492.  
  493.             if ( isalnum( *next_token ) ) 
  494.             {
  495.                 lpPC->lpParseText = SkipWhiteSpace(next_token);
  496.                 lpPC->ParseState = st_fresh_start;
  497.                 lpPC->ScannedToken = tk_none;
  498.                 return(-1);
  499.             }
  500.  
  501.             lpPC->lpParseText = SkipWhiteSpace(next_token);
  502.             lpPC->ParseState = st_fresh_start;
  503.             lpPC->ScannedToken = tk_number;
  504.             return(0);
  505.         }
  506.         else 
  507.         {
  508. Decimal:
  509.             while ( isdigit( *next_token ) && *next_token ) 
  510.             {
  511.                 next_token++;
  512.             }
  513.  
  514.             //
  515.             // decimal point.
  516.             //
  517.             if ( *next_token == '.' ) 
  518.             {
  519.                 next_token++;
  520.  
  521.                 if ( flag_period ) 
  522.             {
  523.                     lpPC->lpParseText = SkipWhiteSpace(next_token);
  524.                     lpPC->ParseState = st_fresh_start;
  525.                     lpPC->ScannedToken = tk_none;
  526.                     return(-1);
  527.                 }
  528.                 else 
  529.             {
  530.                     flag_period = TRUE;
  531.                     goto Decimal;
  532.                 }
  533.              }
  534.  
  535.              //
  536.              //  exponential form...
  537.              //
  538.              if ( tolower( *next_token ) == 'e' ) 
  539.             {
  540.                 next_token++;
  541.  
  542.                 if ( flag_exp ) 
  543.             {
  544.                     lpPC->lpParseText = SkipWhiteSpace(next_token);
  545.                     lpPC->ParseState = st_fresh_start;
  546.                     lpPC->ScannedToken = tk_none;
  547.                     return(-1);
  548.                 }
  549.                 else 
  550.             {
  551.                     flag_exp = TRUE;
  552.  
  553.                     if ( *next_token == '+' || *next_token == '-' ) 
  554.                {
  555.                         next_token++;
  556.                     }
  557.  
  558.                     if ( !isdigit( *next_token ) ) 
  559.                     {
  560.                         lpPC->lpParseText = SkipWhiteSpace(++next_token);
  561.                         lpPC->ParseState = st_fresh_start;
  562.                         lpPC->ScannedToken = tk_none;
  563.                         return(-1);
  564.                     }
  565.  
  566.                     goto Decimal;
  567.                 }
  568.             }
  569.  
  570.             if ( flag_exp || flag_period ) 
  571.             {
  572.                 if ( (( tolower( *next_token ) == 'l' )  || 
  573.                       ( tolower( *next_token ) == 'f' )) && !isalnum( *(next_token + 1) ) 
  574.                    )
  575.                 {
  576.                     next_token += 1;
  577.                 }
  578.             }
  579.             
  580.             else 
  581.             {
  582.                 if ( (( tolower( *next_token ) == 'l' )  || 
  583.                       ( tolower( *next_token ) == 'u' )) && !isalnum( *(next_token + 1) ) 
  584.                    )
  585.                 {
  586.                     next_token += 1;
  587.                 }
  588.             }
  589.  
  590.             if ( isalpha( *next_token ) ) 
  591.             {
  592.                 lpPC->lpParseText  = SkipWhiteSpace(++next_token);
  593.                 lpPC->ParseState = st_fresh_start;
  594.                 lpPC->ScannedToken = tk_none;
  595.                 return(-1);
  596.             }
  597.  
  598.             lpPC->lpParseText = SkipWhiteSpace(next_token);
  599.             lpPC->ParseState = st_fresh_start;
  600.             lpPC->ScannedToken = tk_number;
  601.             return(0);
  602.         }
  603.     }
  604.  
  605.     // Keywords...
  606.     else 
  607.     {
  608.         tmp_pointer = next_token;
  609.  
  610.         //
  611.         //  Suck it in...
  612.         //
  613.         while (( isalnum( *tmp_pointer ) || *tmp_pointer == '_' ) && *tmp_pointer ) {
  614.             tmp_pointer++;
  615.         }
  616.  
  617.         lpPC->lpParseText = SkipWhiteSpace(tmp_pointer);
  618.  
  619.         // So it doesn't crap out for long non-keywords
  620.         if ( (tmp_pointer - next_token) > 10 ) 
  621.         {
  622.            lpPC->ParseState = st_fresh_start;
  623.            lpPC->ScannedToken = tk_none;
  624.            return(0);
  625.         }
  626.  
  627.         strncpy( akeyword, next_token, (tmp_pointer - next_token) );
  628.         akeyword[ tmp_pointer - next_token ] = '\0';
  629.  
  630.         if ( is_c_keyword( akeyword ) ) 
  631.       {
  632.            lpPC->ParseState = st_fresh_start;
  633.            lpPC->ScannedToken = tk_keyword;
  634.            return(0);
  635.         }
  636.  
  637.         lpPC->ParseState   = st_fresh_start;
  638.         lpPC->ScannedToken = tk_none;
  639.         return(0);
  640.     }
  641. }
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648. ////////////////////////////////////////////////////////////////////////
  649. //
  650. //  Internal Routines...
  651. //
  652. ////////////////////////////////////////////////////////////////////////
  653.  
  654. static int isodigit( char digit )
  655. {
  656.     if ( digit >= '0' && digit <= '7' )
  657.         return( TRUE );
  658.  
  659.     return( FALSE );
  660. }
  661.  
  662.  
  663.  
  664.  
  665. static BOOL test_continuation(char *next_token)
  666. {
  667.    return( (*next_token) && (*next_token == '\\') && !*(next_token+1) );
  668. }
  669.  
  670.  
  671.  
  672.  
  673.  
  674. static BOOL scan_comment_conditions(char *text)
  675. {
  676.    char *scan_text, *sptr;
  677.    char *close_comment;
  678.    char *open_comment;
  679.    char *quote;
  680.    //char *pound;
  681.  
  682.    if ( text == NULL ) return(FALSE);
  683.  
  684.    sptr = scan_text = (char *)malloc(strlen(text)+1);
  685.    strcpy(scan_text,text);
  686.  
  687.    close_comment = strstr(scan_text, "*/");
  688.    open_comment  = strstr(scan_text, "/*");
  689.    quote         = strstr(scan_text, "\"");
  690.  
  691.    if ( !quote )
  692.      if ( open_comment || close_comment ) 
  693.      {
  694.         free(sptr);
  695.         return(TRUE);
  696.      }
  697.  
  698.    free(sptr);
  699.  
  700.    return(FALSE);
  701. }
  702.    
  703.  
  704.  
  705.  
  706. static char *scan_from_preprocessor( char                *next_token, 
  707.                                      parse_context_type  *lpPC )
  708. {
  709.    while ( *next_token ) 
  710.    {
  711.       if ( (*next_token == '/') &&
  712.            (*(next_token + 1) == '/') )
  713.          break;
  714.  
  715.       if ( (*next_token == '/') &&
  716.            (*(next_token + 1) == '*') )
  717.          break;
  718.             
  719.       if ( test_continuation(next_token) )
  720.       {
  721.          lpPC->ParseState = st_continue_previous;
  722.          next_token++;
  723.          break;
  724.       }
  725.  
  726.       lpPC->ParseState = st_fresh_start;
  727.       next_token++;
  728.    }
  729.  
  730.    return(next_token);
  731. }
  732.  
  733.  
  734.  
  735.  
  736.  
  737. static char *scan_comment(char *next_token, parse_context_type *lpPC)
  738. {            
  739.    BOOL done;
  740.  
  741.    done = FALSE;
  742.    while ( !done ) 
  743.    {
  744.        while ( (*next_token != '/') && *next_token ) 
  745.       {
  746.           next_token++;
  747.         }
  748.         
  749.       if ( *(next_token - 1) == '*' || !(*next_token) ) 
  750.       {
  751.          if ( !(*next_token) )
  752.             lpPC->ParseState = st_continue_comment;
  753.          else
  754.             lpPC->ParseState = st_fresh_start;
  755.  
  756.            done = TRUE;
  757.         }
  758.  
  759.         if ( *next_token ) next_token++;
  760.     }
  761.  
  762.    return(next_token);
  763. }
  764.  
  765.  
  766.  
  767.  
  768.  
  769. static char *scan_string(char *next_token, parse_context_type *lpPC)
  770. {            
  771.    while ( (*next_token != '"') && *next_token ) 
  772.    {
  773.       if ( test_continuation(next_token) )
  774.       {
  775.          lpPC->ParseState = st_continue_previous;
  776.          ++next_token;
  777.          break;
  778.       }
  779.  
  780.       lpPC->ParseState = st_fresh_start;
  781.       if ( *next_token == '\\' ) next_token++;
  782.       next_token++;
  783.    }
  784.  
  785.    if ( *next_token ) ++next_token;
  786.  
  787.    return(next_token);
  788. }
  789.  
  790.  
  791.  
  792.  
  793. //
  794. //  Keyword stuff...
  795. //
  796. static int is_c_keyword( char *token )
  797. {
  798.    typedef struct keyword_type
  799.    {
  800.       char *kw;
  801.       BOOL  lang;
  802.    }
  803.    keyword_type;
  804.  
  805.     static keyword_type keywords_2[] = 
  806.    {
  807.         "do", C_KEYWORD|CPP_KEYWORD,    /* C   */
  808.         "if", C_KEYWORD|CPP_KEYWORD,   /* C   */
  809.         NULL, NULL 
  810.     };
  811.  
  812.     static keyword_type keywords_3[] = 
  813.    {
  814.        "for", C_KEYWORD|CPP_KEYWORD,   /* C   */
  815.        "int", C_KEYWORD|CPP_KEYWORD,   /* C   */
  816.        "asm", CPP_KEYWORD,  /* C++?*/
  817.        "new", CPP_KEYWORD,   /* C++ */
  818.        "try", CPP_KEYWORD,   /* C++ */
  819.        NULL, NULL
  820.    };
  821.  
  822.     static keyword_type keywords_4[] = {
  823.                                    "auto", C_KEYWORD|CPP_KEYWORD,   /* C   */
  824.                                    "case", C_KEYWORD|CPP_KEYWORD,   /* C   */
  825.                                    "char", C_KEYWORD|CPP_KEYWORD,   /* C   */
  826.                                    "else", C_KEYWORD|CPP_KEYWORD,   /* C   */
  827.                                    "enum", C_KEYWORD|CPP_KEYWORD,   /* C   */
  828.                                    "goto", C_KEYWORD|CPP_KEYWORD,   /* C   */
  829.                                    "long", C_KEYWORD|CPP_KEYWORD,   /* C   */
  830.                                    "void", C_KEYWORD|CPP_KEYWORD,   /* C   */
  831.                                    "bool", CPP_KEYWORD,   /* New as of GCC 2.6.0  */
  832.                                    "this", CPP_KEYWORD,   /* C++ */
  833.                                    NULL, NULL 
  834.                                  };
  835.  
  836.     static keyword_type keywords_5[] = {
  837.                                    "break", C_KEYWORD|CPP_KEYWORD,   /* C   */
  838.                                    "const", C_KEYWORD|CPP_KEYWORD,   /* C   */
  839.                                    "float", C_KEYWORD|CPP_KEYWORD,   /* C   */
  840.                                    "short", C_KEYWORD|CPP_KEYWORD,   /* C   */
  841.                                    "union", C_KEYWORD|CPP_KEYWORD,   /* C   */
  842.                                    "while", C_KEYWORD|CPP_KEYWORD,   /* C   */
  843.                                    "catch", CPP_KEYWORD,   /* C++ */
  844.                                    "class", CPP_KEYWORD,   /* C++ */
  845.                                    "throw", CPP_KEYWORD,   /* C++ */
  846.                                    NULL, NULL 
  847.                                  };
  848.  
  849.     static keyword_type keywords_6[] = {
  850.                                    "double", C_KEYWORD|CPP_KEYWORD,   /* C   */
  851.                                    "extern", C_KEYWORD|CPP_KEYWORD,   /* C   */
  852.                                    "return", C_KEYWORD|CPP_KEYWORD,   /* C   */
  853.                                    "signed", C_KEYWORD|CPP_KEYWORD,   /* C   */
  854.                                    "sizeof", C_KEYWORD|CPP_KEYWORD,   /* C   */
  855.                                    "static", C_KEYWORD|CPP_KEYWORD,   /* C   */
  856.                                    "struct", C_KEYWORD|CPP_KEYWORD,   /* C   */
  857.                                    "switch", C_KEYWORD|CPP_KEYWORD,   /* C   */
  858.                                    "delete", CPP_KEYWORD,   /* C++ */
  859.                                    "friend", CPP_KEYWORD,   /* C++ */
  860.                                    "inline", CPP_KEYWORD,   /* C++ */
  861.                                    "public", CPP_KEYWORD,   /* C++ */
  862.                                    NULL, NULL 
  863.                                  };
  864.  
  865.     static keyword_type keywords_7[] = {
  866.                                    "default", C_KEYWORD|CPP_KEYWORD,   /* C   */
  867.                                    "typedef", C_KEYWORD|CPP_KEYWORD,   /* C   */
  868.                                    "private", CPP_KEYWORD,   /* C++ */
  869.                                    "virtual", CPP_KEYWORD,   /* C++ */
  870.                                    NULL, NULL 
  871.                                  };
  872.  
  873.     static keyword_type keywords_8[] = {
  874.                                    "continue", C_KEYWORD|CPP_KEYWORD,   /* C   */
  875.                                    "register", C_KEYWORD|CPP_KEYWORD,   /* C   */
  876.                                    "unsigned", C_KEYWORD|CPP_KEYWORD,   /* C   */
  877.                                    "volatile", C_KEYWORD|CPP_KEYWORD,   /* C   */
  878.                                    "operator", CPP_KEYWORD,   /* C++ */
  879.                                    "template", CPP_KEYWORD,   /* C++ */
  880.                                    NULL, NULL 
  881.                                  };
  882.  
  883.     static keyword_type keywords_9[] = {
  884.                                    "protected", CPP_KEYWORD,   /* C++ */
  885.                                    NULL, NULL 
  886.                                  };
  887.                               
  888.     int    count = 0;
  889.     keyword_type *    keywords;
  890.  
  891.     switch ( strlen( token ) ) {
  892.         case 2: keywords = keywords_2;
  893.                 break;
  894.         case 3: keywords = keywords_3;
  895.                 break;
  896.         case 4: keywords = keywords_4;
  897.                 break;
  898.         case 5: keywords = keywords_5;
  899.                 break;
  900.         case 6: keywords = keywords_6;
  901.                 break;
  902.         case 7: keywords = keywords_7;
  903.                 break;
  904.         case 8: keywords = keywords_8;
  905.                 break;
  906.         case 9: keywords = keywords_9;
  907.                 break;
  908.         default: return( FALSE );
  909.     }
  910.  
  911.     for ( ; keywords[ count ].kw != NULL; count++ ) {
  912.         if (  strcmp( keywords[ count ].kw, token ) == 0 &&
  913.            (keywords[ count ].lang & cpp->keywords) )
  914.             return( TRUE );
  915.     }
  916.  
  917.     return( FALSE );
  918.  
  919. }
  920.